package com.ofek.eventos.gui.list_table;


import java.lang.reflect.Field;
import java.util.ArrayList;

import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

import com.ofek.eventos.db.datatypes.helptypes.TableFieldInfo;
import com.ofek.eventos.db.datatypes.helptypes.TableFieldInfo.Converter;

/**
 * The ListTableModel contains all methods for initialize the table model of change requests
 *  
 * @author Ofek Ron
 * @author Avihay Avitan
 * @author Nitzan Inbar
 * @author Sasha Rozenblum
 */
public class ListTableModel<T> implements TableModel {
	/**
	 * listeners - Array List of Table Model Listeners
	 */
	private final ArrayList<TableModelListener> listeners = new ArrayList<TableModelListener>();
	/**
	 * mElements - Array List of Table Model Elements
	 */
	private final ArrayList<T> mElements;
	/**
	 * representingItem - The items to display
	 */
	private T representingItem;
	/**
	 * fields - The field names of items
	 */
	private final ArrayList<Field> fields = new ArrayList<Field>();
	/**
	 * Constructs the ListTableModel.
	 * initialize the items to be displayed in the table
	 * @param req - ArrayList of change requests items to display
	 */
	public ListTableModel(final ArrayList<T> req) {
		mElements=req;
		if (mElements.size()>0) {
			representingItem=mElements.get(0);
			for (final Field f : representingItem.getClass().getDeclaredFields()) {
				final TableFieldInfo anno = f.getAnnotation(TableFieldInfo.class);
				if (anno!=null && anno.isVisibleOnTable()) fields.add(f);
			}

		}

	}

	/**
	 * Gets the change request at row i
	 * @param i - The row index of the requested ChangeRequest
	 * @return mElements.get(i) - the ChangeRequest 
	 */
	public T getChangeRequest(final int i) {
		return mElements.get(i);
	}
	/**
	 * Add listener to TableModel
	 * @param l - The TableModelListener to add
	 */
	@Override
	public void addTableModelListener(final TableModelListener l) {
		if (!listeners.contains(l))
			listeners.add(l);
	}

	@Override
	public Class<?> getColumnClass(final int arg0) {
		return String.class;
	}
	/**
	 * Gets the element at row i
	 * @param i - The row index of the requested element
	 * @return mElements.get(i) - the element 
	 */
	public T get(final int i) {
		return mElements.get(i);
	}


	@Override
	public int getRowCount() {
		return mElements.size();
	}


	@Override
	public boolean isCellEditable(final int arg0, final int arg1) {
		return false;
	}

	@Override
	public void removeTableModelListener(final TableModelListener l) {
		listeners.remove(l);
	}

	@Override
	public void setValueAt(final Object arg0, final int arg1, final int arg2) {
	}

	@Override
	public int getColumnCount() {


		return fields.size();
	}
	@Override
	public String getColumnName(final int columnIndex) {
		return fields.get(columnIndex).getAnnotation(TableFieldInfo.class).name();
	}
	@Override
	public Object getValueAt(final int rowIndex, final int columnIndex) {
		try {
			final Field f = fields.get(columnIndex);
			final Class<? extends Converter> converterClass = f.getAnnotation(TableFieldInfo.class).converterType();
			Converter converter =null;
			try {
				converter = converterClass.newInstance();
			} catch (final InstantiationException e) {
				e.printStackTrace();
			}
			final boolean b = f.isAccessible();
			f.setAccessible(true);
			final Object value = f.get(get(rowIndex));
			f.setAccessible(b);
			return converter.convert(value);
		} catch (final IllegalArgumentException e) {
			e.printStackTrace();
		} catch (final SecurityException e) {
			e.printStackTrace();
		} catch (final IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}

}
